package com.tongji.housediy.utils
{
	import com.tongji.housediy.view.components.AbstractBorderChild;
	import com.tongji.housediy.view.components.AbstractDrawingRoom;
	import com.tongji.housediy.view.components.RoomShape;
	
	import flash.display.DisplayObject;
	import flash.display.Shape;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.geom.Vector3D;

	/**
	 * 
	 * @author chenchao
	 * 
	 */
	public class MathCalculation
	{	
		static private var shape:Shape = new Shape();
		
		static public function getZoomMultiple():Number
		{
			if (ConstVariableInventory.currentScrollbarValue != ConstVariableInventory.SCROLLBAR_INITIAL_VALUE)
				return Math.pow(ConstVariableInventory.WHEEL_SCALE_UP, (ConstVariableInventory.currentScrollbarValue - ConstVariableInventory.SCROLLBAR_INITIAL_VALUE));
			else
				return 1;
		}
		
		static public function calculateOffsetPoint(initialPoint:Point, rotation:Number):Point
		{
			var matrix:Matrix = new Matrix();
			matrix.rotate(rotation * Math.PI / 180);
			return matrix.deltaTransformPoint(initialPoint);
		}
		
		/**
		 * 计算 RoomBorder 孩子对应于 RoomBorder 斜率，需要移动的偏移量
		 * @param k RoomBorder 的斜率
		 * @param length 拖拽至 RoomBorder 上的子元件的长度
		 * @param data RoomBorder 上两个顶点的坐标向量
		 * @return 返回偏移量，相对于（0,0）
		 * 
		 */		
		static public function getOffsetValue(k:Number, length:Number, data:Vector.<Number>):Point
		{
			shape.x = 0;
			shape.y = length;
			
			var matrix:Matrix = shape.transform.matrix;
			if (k > 0)
				matrix.rotate(Math.atan(k) - Math.PI / 2);
			else
				matrix.rotate(Math.PI / 2 + Math.atan(k));
			shape.transform.matrix = matrix;
			
			if (data[0] != data[2])
			{
				if (data[3] > data[1])
					return new Point(shape.x, shape.y);
				else if (data[3] < data[1])
					return new Point(-shape.x, -shape.y);
				else if (data[3] == data[1])
				{
					if (data[0] < data[2]) return new Point(length, 0);
					else return new Point(-length, 0);
				}
			}
			else
			{
				if (data[3] > data[1])
					return new Point(0, length);
				else return new Point(0, -length);
			}
			
			return null;
		}
		
		/**
		 * 计算 RoomBorder 的斜率
		 * @param data RoomBorder 上两个顶点的坐标向量
		 * @return 返回 RoomBorder 的斜率
		 * 
		 */		
		static public function calculateGradient(data:Vector.<Number>):Number
		{
			if (data[0] != data[data.length - 2])
				return (data[1] - data[data.length - 1]) / (data[0] - data[data.length - 2]);
			else
				return Infinity;
		}
		
		/**
		 * 计算拖拽 RoomBorder 子元件时，鼠标位置同 RoomBorder 直线的垂足点坐标
		 * @param k RoomBorder 的斜率
		 * @param data RoomBorder 上两个顶点的坐标向量
		 * @param clickPoint 鼠标当前坐标
		 * @return 返回垂直坐标点
		 * 
		 */		
		static public function getPedalPoint(k:Number, data:Vector.<Number>, clickPoint:Point):Point
		{
			var x:Number;
			var y:Number;
			//if (k != )
			if (data[0] != data[data.length - 2])
			{
				x = (k * k * data[0] + k * (clickPoint.y - data[1]) + clickPoint.x) / (k * k + 1);
				y = k * (x - data[0]) + data[1];
			}
			else
			{
				x = data[0];
				y = clickPoint.y;
			}
			return new Point(x, y);
		}
		
		/**
		 * 判断当前点是否处于两点组成的包围盒内
		 * @param firstX 第一个点的 X 轴坐标
		 * @param firstY 第一个点的 Y 轴坐标
		 * @param lastX 第二个点的 X 轴坐标
		 * @param lastY 第一个点的 Y 轴坐标
		 * @param currentX 当前点的 X 轴坐标
		 * @param currentY 当前点的 Y 轴坐标
		 * @return 返回是否处于包围盒内的布尔型变量
		 * 
		 */		
		static public function isInMiddlePosition(firstX:Number, firstY:Number, lastX:Number, lastY:Number, currentX:Number, currentY:Number):Boolean
		{
			if (firstX == lastX)
			{
				if ((firstY < currentY && currentY < lastY) || (lastY < currentY && currentY < firstY))
					return true;
				else
					return false;
			}
			else
			{
				if ((firstX < currentX && currentX < lastX) || (lastX < currentX && currentX < firstX))
					return true;
				else
					return false;
			}
		}
		
		/**
		 * 通过 自身 坐标系 来 旋转 DisplayObject
		 * @param displayOb 需要旋转的物体
		 * @param regPiont 旋转中心点坐标（基于 自身 坐标系）
		 * @param angleDegrees 旋转角度（弧度）
		 * @param sx
		 * @param sy
		 * 
		 */		
		public static function transformWithExternalPoint(displayOb:DisplayObject, regPiont:Point, angleDegrees:Number = 0, sx:Number = 1, sy:Number = 1):Matrix 
		{
			var m:Matrix = displayOb.transform.matrix;
			var returnMatrix:Matrix = displayOb.transform.matrix;
			m.tx -= regPiont.x;
			m.ty -= regPiont.y;
			/*if (angleDegrees % 360 != 0) {
				m.rotate(angleDegrees*(Math.PI/180));
			}*/
			m.rotate(angleDegrees);
			if (sx != 1 || sy != 1) {
				m.scale(sx,sy);
			}
			m.tx += regPiont.x;
			m.ty += regPiont.y;
			displayOb.transform.matrix = m;
			
			return returnMatrix;
		}
		
		/**
		 * 通过 父容器 坐标系 来 旋转 DisplayObject
		 * @param displayOb 需要旋转的物体
		 * @param regPiont 旋转中心点坐标（基于 父容器 坐标系）
		 * @param angleDegrees 旋转角度（弧度）
		 * @param sx
		 * @param sy
		 * 
		 */		
		public static function transformWithInternalPoint(displayOb:DisplayObject, regPiont:Point, angleDegrees:Number = 0, sx:Number = 1, sy:Number = 1):void 
		{
			var m:Matrix = displayOb.transform.matrix;
			regPiont = m.transformPoint(regPiont);
			m.tx -= regPiont.x;
			m.ty -= regPiont.y;
			/*if (angleDegrees % 360 != 0) {
				m.rotate(angleDegrees*(Math.PI/180));
			}*/
			m.rotate(angleDegrees);
			if (sx != 1 || sy != 1) {
				m.scale(sx,sy);
			}
			m.tx += regPiont.x;
			m.ty += regPiont.y;
			displayOb.transform.matrix = m;
		}
		
		/**
		 * 获得三点夹角度数（弧度值）
		 * @param x1 中心点 X 轴坐标值
		 * @param y1 中心点 Y 轴坐标值
		 * @param x2 邻边点1 X 轴坐标值
		 * @param y2 邻边点1 Y 轴坐标值
		 * @param x3 邻边点2 X 轴坐标值
		 * @param y3 邻边点2 Y 轴坐标值
		 * @return 返回夹角弧度值
		 * 
		 */		
		public static function getRotationAngle(x1:Number, y1:Number, x2:Number, y2:Number, x3:Number, y3:Number):Number
		{
			var va:Vector3D = new Vector3D((x2 - x1), (y2 - y1), 0);
			var vb:Vector3D = new Vector3D((x3 - x1), (y3 - y1), 0);
			var vJudge:Vector3D;
			var angle:Number;
			
			if(va.equals(vb))
				return 0;
			else
			{
				angle = Vector3D.angleBetween(va, vb);
				vJudge = va.crossProduct(vb);
				
				if(vJudge.z >= 0)
					return angle;
				else
					return -angle;
			}
		}
		///////////////////////////////by zazisb
		public static function getRoomBorderVectorAngle(x1:Number, y1:Number, x2:Number, y2:Number, x3:Number, y3:Number, x4:Number, y4:Number):Number
		{
			var va:Vector3D = new Vector3D((x2 - x1), (y2 - y1), 0);
			var vb:Vector3D = new Vector3D((x4 - x3), (y4 - y3), 0);
			var angle:Number;
			
			if(va.equals(vb))
				return 0;
			else
			{
				angle = Vector3D.angleBetween(va, vb);
				return angle;
			}
		}
		
		public static function transExPtFromInPt(roomShape:RoomShape, point:Point):Point 
		{
			var room:AbstractDrawingRoom;
			
			if(!(roomShape is AbstractBorderChild))
				room = roomShape.parent as AbstractDrawingRoom;
			else
				room = roomShape.parent.parent as AbstractDrawingRoom;
			
			return new Point(room.x + point.x, room.y + point.y);
		}
		
		public static function transInPtFromExPt(roomShape:RoomShape, point:Point):Point 
		{
			var room:AbstractDrawingRoom;
			
			if(!(roomShape is AbstractBorderChild))
				room = roomShape.parent as AbstractDrawingRoom;
			else
				room = roomShape.parent.parent as AbstractDrawingRoom;
			
			return new Point(point.x - room.x, point.y - room.y);
		}
		
		public static function getTwoPtInFourPt(point1:Point, point2:Point, point3:Point, point4:Point):Array 
		{
			var max:Number = Math.max(point1.x, point2.x, point3.x, point4.x);
			var min:Number = Math.min(point1.x, point2.x, point3.x, point4.x);
			var pointArr:Array = new Array(point1, point2, point3, point4);
			
			if (max == min)
			{
				max = Math.max(point1.y, point2.y, point3.y, point4.y);
				min = Math.min(point1.y, point2.y, point3.y, point4.y);
				pointArr = deleteMaxAndMin(pointArr, false, max, min);
				return pointArr;
			}
			else
			{
				pointArr = deleteMaxAndMin(pointArr, true, max, min);
				return pointArr;
			}
		}
		
		public static function deleteMaxAndMin(array:Array, flag:Boolean, max:Number, min:Number):Array
		{
			var i:int;
			
			if(flag)
			{
				for(i = 0; i < array.length; i++)
				{
					if(array[i].x == max)
					{
						array.splice(i, 1);
						break;
					}
				}
				
				for(i = 0; i < array.length; i++)
				{
					if(array[i].x == min)
					{
						array.splice(i, 1);
						break;
					}
				}
			}
			else
			{
				for(i = 0; i < array.length; i++)
				{
					if(array[i].y == max)
					{
						array.splice(i, 1);
						break;
					}
				}
				
				for(i = 0; i < array.length; i++)
				{
					if(array[i].y == min)
					{
						array.splice(i, 1);
						break;
					}
				}
			}
			return array;
		}
		///////////////////////////////////////////////////////////////
		/**
		 * 通过两个坐标点，构建一个 Recangle
		 * @param x1 第一个点的 X 轴坐标
		 * @param y1 第一个点的 Y 轴坐标
		 * @param x2 第二个点的 X 轴坐标
		 * @param y2 第二个点的 Y 轴坐标
		 * @return 返回所构造出来的 Rectangle
		 * 
		 */		
		public static function getRectangleByTwoPoint(x1:Number, y1:Number, x2:Number, y2:Number):Rectangle
		{
			var rectangle:Rectangle = new Rectangle(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x1 - x2), Math.abs(y1 - y2));
			
			if (rectangle.height == 0)
			{
				rectangle.y -= 1;
				rectangle.height = 2;
			}
			else if (rectangle.width == 0)
			{
				rectangle.x -= 1;
				rectangle.width = 2;
			}
			
			return rectangle;
		}
		
		/**
		 * 判断房间形状的是否反转
		 * @param data 房间顶点向量数组
		 * @return 房间是否反转
		 * 
		 */		
		public static function isRoomOverTurn(data:Vector.<Number>):Boolean
		{
			var vJudge:Vector3D;
			var zCount:int = 0;
			
			for (var i:int = 4; i <= data.length; i += 2)
			{
				var firstVector3D:Vector3D;
				var secondVector3D:Vector3D;
				
				firstVector3D = new Vector3D(data[i - 2] - data[i - 4], data[i - 1] - data[i - 3], 0);
				
				if (i < data.length)
				{
					secondVector3D = new Vector3D(data[i] - data[i - 2], data[i + 1] - data[i - 1], 0);
				}
				else
				{
					secondVector3D = new Vector3D(data[2] - data[0], data[3] - data[1], 0);
				}
				
				vJudge = firstVector3D.crossProduct(secondVector3D);
				if (vJudge.z > 0)
					zCount++;
				else
					zCount--;
			}
			
			if (zCount > 0)
				return false;
			else
				return true;
		}
	}
}